package com.weijian.service.impl;

import com.weijian.common.result.ApiResponse;
import com.weijian.dal.entity.MatchDetail;
import com.weijian.dal.entity.MatchResult;
import com.weijian.dal.entity.Route;
import com.weijian.dal.entity.Shipment;
import com.weijian.dal.enums.City;
import com.weijian.dal.enums.RouteType;
import com.weijian.dto.data.BatchStatistics;
import com.weijian.dto.match.MatchResultData;
import com.weijian.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * CSV数据处理服务实现类
 * 负责CSV文件的解析和数据保存到数据库
 */
@Service
public class CsvDataServiceImpl implements CsvDataService {

    @Autowired
    private RouteService routeService;

    @Autowired
    private ShipmentService shipmentService;

    @Autowired
    private MatchResultService matchResultService;

    @Autowired
    private MatchDetailService matchDetailService;

    @Autowired
    private TaskService taskService;

    /**
     * 解析并保存路线CSV文件
     *
     * @param file     CSV文件
     * @param batchId  批次ID
     * @return 解析结果
     * @throws IOException IO异常
     */
    @Override
    public ApiResponse<String> parseAndSaveRouteCsv(MultipartFile file, Integer batchId) throws IOException {
        try {
            // 解析CSV文件
            List<Route> routes = parseRouteCsv(file, batchId);

            // 保存到数据库
            if (!routes.isEmpty()) {
                routeService.saveBatch(routes);
                return ApiResponse.success("成功上传并解析" + routes.size() + "条路线数据，batchId: " + batchId);
            } else {
                return ApiResponse.badRequest("未解析到有效路线数据");
            }
        } catch (Exception e) {
            return ApiResponse.internalError("数据保存失败: " + e.getMessage());
        }
    }

    /**
     * 解析并保存货物CSV文件
     *
     * @param file     CSV文件
     * @param batchId  批次ID
     * @return 解析结果
     * @throws IOException IO异常
     */
    @Override
    public ApiResponse<String> parseAndSaveShipmentCsv(MultipartFile file, Integer batchId) throws IOException {
        try {
            // 解析CSV文件
            List<Shipment> shipments = parseShipmentCsv(file, batchId);

            // 保存到数据库
            if (!shipments.isEmpty()) {
                shipmentService.saveBatch(shipments);
                return ApiResponse.success("成功上传并解析" + shipments.size() + "条货物数据，batchId: " + batchId);
            } else {
                return ApiResponse.badRequest("未解析到有效货物数据");
            }
        } catch (Exception e) {
            return ApiResponse.internalError("数据保存失败: " + e.getMessage());
        }
    }

    /**
     * 解析并保存稳定匹配结果CSV文件
     *
     * @param file     CSV文件
     * @param batchId  批次ID
     * @return 解析结果
     * @throws IOException IO异常
     */
    @Override
    public ApiResponse<String> parseAndSaveMatchResultCsv(MultipartFile file, Integer batchId) throws IOException {
        try {
            // 解析CSV文件获取匹配结果和详情
            MatchResultData matchResultData = parseMatchResultCsv(file, batchId);

            // 保存匹配结果到数据库
            ApiResponse<Integer> saveResult = saveMatchResultData(matchResultData, null, batchId);

            if (saveResult.getCode() == 200) {
                return ApiResponse.success("成功保存匹配结果数据和详情数据，batchId: " + batchId + "，匹配结果ID: " + saveResult.getData());
            } else {
                return ApiResponse.badRequest("保存匹配结果失败: " + saveResult.getMessage());
            }
        } catch (Exception e) {
            return ApiResponse.internalError("数据保存失败: " + e.getMessage());
        }
    }

    /**
     * 保存稳定匹配结果数据（从已解析的数据）
     *
     * @param matchResultData 匹配结果数据
     * @param taskId 关联的任务ID
     * @param batchId 批次ID
     * @return 保存结果，包含匹配结果ID
     */
    @Override
    public ApiResponse<Integer> saveMatchResultData(MatchResultData matchResultData, String taskId, Integer batchId) {
        MatchResult matchResult = matchResultData.getMatchResult();
        // 保存匹配结果到数据库
        if (matchResult != null) {
            if (taskId != null) {
                com.weijian.dal.entity.Task task = taskService.lambdaQuery().eq(com.weijian.dal.entity.Task::getTaskNo, taskId).one();
                if (task != null) {
                    matchResult.setTaskId(task.getTaskId());
                }
            }
            matchResult.setDataId(batchId);
            matchResultService.save(matchResult);

            // 获取保存后的匹配结果ID
            Integer matchResultId = matchResult.getId();

            // 设置匹配结果ID并保存匹配详情
            if (matchResultId != null && matchResultData.getMatchDetails() != null
                    && !matchResultData.getMatchDetails().isEmpty()) {
                matchResultData.getMatchDetails().forEach(detail -> detail.setMatchResultId(matchResultId));
                matchResultData.getMatchDetails().forEach(detail -> detail.setDataId(batchId));
                matchDetailService.saveBatch(matchResultData.getMatchDetails());
            }

            return ApiResponse.success("成功保存匹配结果数据和详情数据", matchResultId);
        } else {
            return ApiResponse.badRequest("未解析到有效匹配结果数据");
        }
    }

    /**
     * 解析路线CSV文件
     *
     * @param file    CSV文件
     * @param dataId  数据ID
     * @return 路线列表
     * @throws IOException IO异常
     */
    @Override
    public List<Route> parseRouteCsv(MultipartFile file, Integer dataId) throws IOException {
        List<Route> routes = new ArrayList<>();
        // 用于跟踪数据行号（从1开始）
        int dataRowNumber = 0;

        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(file.getInputStream(), StandardCharsets.UTF_8))) {

            // 跳过第一行元数据
            reader.readLine();

            // 跳过标题行
            reader.readLine();

            String line;
            while ((line = reader.readLine()) != null) {
                // 跳过空行
                if (!line.trim().isEmpty()) {
                    dataRowNumber++;
                    String[] rowData = line.split(",", -1);
                    Route route = parseRouteFromCsvRow(rowData, dataId, dataRowNumber);
                    if (route != null) {
                        routes.add(route);
                    }
                }
            }
        }

        return routes;
    }

    /**
     * 解析货物CSV文件
     *
     * @param file    CSV文件
     * @param dataId  数据ID
     * @return 货物列表
     * @throws IOException IO异常
     */
    @Override
    public List<Shipment> parseShipmentCsv(MultipartFile file, Integer dataId) throws IOException {
        List<Shipment> shipments = new ArrayList<>();

        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(file.getInputStream(), StandardCharsets.UTF_8))) {

            // 跳过第一行数据
            reader.readLine();

            // 读取标题行
            String headerLine = reader.readLine();
            if (headerLine == null) {
                return shipments; // 空文件
            }

            String[] headers = headerLine.split(",", -1);
            // 创建列索引映射
            Map<String, Integer> headerMap = new HashMap<>();
            for (int i = 0; i < headers.length; i++) {
                headerMap.put(headers[i].trim(), i);
            }

            String line;
            while ((line = reader.readLine()) != null) {
                String[] rowData = line.split(",", -1);
                Shipment shipment = parseShipmentFromCsvRow(rowData, headerMap, dataId);
                if (shipment != null) {
                    shipments.add(shipment);
                }
            }
        }

        return shipments;
    }

    /**
     * 解析稳定匹配结果CSV文件
     *
     * @param file    CSV文件
     * @param dataId  数据ID
     * @return 匹配结果数据（包含匹配结果和匹配详情）
     * @throws IOException IO异常
     */
    @Override
    public MatchResultData parseMatchResultCsv(MultipartFile file, Integer dataId) throws IOException {
        MatchResultData resultData = new MatchResultData();

        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(file.getInputStream(), StandardCharsets.UTF_8))) {

            // 读取Shipment标题行
            String shipmentHeaderLine = reader.readLine();
            if (shipmentHeaderLine == null) {
                return resultData; // 空文件
            }

            // 读取路线分配行（实际数据行）
            String routeLine = reader.readLine();
            if (routeLine == null) {
                return resultData;
            }

            // 读取统计信息行
            List<String> statisticsLines = new ArrayList<>();
            String line;
            while ((line = reader.readLine()) != null) {
                if (!line.trim().isEmpty()) {
                    statisticsLines.add(line);
                }
            }

            // 解析数据
            String[] shipmentHeaderData = shipmentHeaderLine.split(",", -1);
            String[] routeData = routeLine.split(",", -1);

            MatchResult matchResult = parseMatchResultFromCsvRows(shipmentHeaderData, routeData, statisticsLines, dataId);
            List<MatchDetail> matchDetails = parseMatchDetailsFromCsvRows(shipmentHeaderData, routeData, dataId);

            resultData.setMatchResult(matchResult);
            resultData.setMatchDetails(matchDetails);
        }

        return resultData;
    }

    /**
     * 解析稳定匹配结果CSV文件
     *
     * @param file    CSV文件
     * @param dataId  数据ID
     * @return 匹配结果数据（包含匹配结果和匹配详情）
     * @throws IOException IO异常
     */
    @Override
    public MatchResultData parseMatchResultCsv(File file, Integer dataId) throws IOException {
        // 创建一个简单的MultipartFile实现并复用现有方法
        MultipartFile multipartFile = new CustomMultipartFile(file);
        return parseMatchResultCsv(multipartFile, dataId);
    }

    /**
     * 检查指定批次下是否已存在路线数据
     *
     * @param dataId 批次ID
     * @return 是否存在路线数据
     */
    @Override
    public boolean isRouteDataExists(Integer dataId) {
        if (dataId == null) {
            return false;
        }
        Long count = routeService.lambdaQuery().eq(Route::getDataId, dataId).count();
        return count > 0;
    }

    /**
     * 检查指定批次下是否已存在货物数据
     *
     * @param dataId 批次ID
     * @return 是否存在货物数据
     */
    @Override
    public boolean isShipmentDataExists(Integer dataId) {
        if (dataId == null) {
            return false;
        }
        Long count = shipmentService.lambdaQuery().eq(Shipment::getDataId, dataId).count();
        return count > 0;
    }

    /**
     * 获取批次的统计信息
     *
     * @param dataId 批次ID
     * @return 统计信息
     */
    @Override
    public BatchStatistics getBatchStatistics(Integer dataId) {
        if (dataId == null) {
            return new BatchStatistics(0L, 0L);
        }

        Long routeCount = routeService.lambdaQuery().eq(Route::getDataId, dataId).count();
        Long shipmentCount = shipmentService.lambdaQuery().eq(Shipment::getDataId, dataId).count();

        return new BatchStatistics(routeCount, shipmentCount);
    }

    /**
     * 从CSV行数据创建路线实例
     *
     * @param rowData       CSV行数据
     * @param dataId        数据ID
     * @param dataRowNumber 数据行号（从1开始）
     * @return 路线实例
     */
    private Route parseRouteFromCsvRow(String[] rowData, Integer dataId, int dataRowNumber) {
        // 跳过标题行和字段名行
        if (rowData.length < 30 || rowData[0].trim().isEmpty() || "route number".equals(rowData[0])) {
            return null;
        }

        try {
            Route route = new Route();
            route.setDataId(dataId);

            // 解析路线ID（第1列）
            route.setRouteId(Integer.parseInt(rowData[0]));

            // 根据行号范围确定路线类型
            // 1-9是西海路新通道，10-12是长江经济带，13-17是跨境公路
            if (dataRowNumber >= 1 && dataRowNumber <= 9) {
                route.setRouteType(RouteType.WEST_SEA_ROUTE);
            } else if (dataRowNumber >= 10 && dataRowNumber <= 12) {
                route.setRouteType(RouteType.YANGTZE_RIVER_ECONOMIC_BELT);
            } else if (dataRowNumber >= 13 && dataRowNumber <= 17) {
                route.setRouteType(RouteType.CROSS_BORDER_HIGHWAY);
            } else {
                // 默认为西海路新通道
                route.setRouteType(RouteType.WEST_SEA_ROUTE);
            }

            // 解析节点数（第3列）
            int nodesCount = rowData[2].trim().isEmpty() ? 0 : Integer.parseInt(rowData[2]);

            // 解析节点列表（第4-12列，共9个字段）
            List<City> nodes = new ArrayList<>();
            for (int i = 3; i < 12 && i < rowData.length; i++) { // CSV数组索引从3开始（第4列到第12列）
                String nodeVal = rowData[i].trim();
                if (!nodeVal.isEmpty() && !"-1".equals(nodeVal)) {
                    try {
                        int nodeCode = Integer.parseInt(nodeVal);
                        City city = City.fromCode(nodeCode);
                        if (city != null) {
                            nodes.add(city);
                        }
                    } catch (NumberFormatException e) {
                        // 忽略无法解析的值
                        continue;
                    }
                }
            }

            // 如果解析的节点数与nodesCount不一致，使用实际解析的节点
            if (nodes.size() != nodesCount) {
                if (nodesCount < nodes.size()) {
                    nodes = nodes.subList(0, nodesCount);
                }
            }
            route.setNodes(nodes);

            // 解析运费列表（第13-21列，共9个字段）
            List<Double> costs = new ArrayList<>();
            for (int i = 12; i < 21 && i < rowData.length; i++) { // CSV数组索引从12开始（第13列到第21列）
                String costVal = rowData[i].trim();
                if (!costVal.isEmpty() && !"-1".equals(costVal)) {
                    try {
                        costs.add(Double.parseDouble(costVal));
                    } catch (NumberFormatException e) {
                        // 忽略无法解析的值
                        continue;
                    }
                }
            }
            route.setCosts(costs);

            // 解析旅行时间列表（第22-30列，共9个字段）
            List<Double> travelTimes = new ArrayList<>();
            for (int i = 21; i < 30 && i < rowData.length; i++) { // CSV数组索引从21开始（第22列到第30列）
                String timeVal = rowData[i].trim();
                if (!timeVal.isEmpty() && !"-1".equals(timeVal)) {
                    try {
                        travelTimes.add(Double.parseDouble(timeVal));
                    } catch (NumberFormatException e) {
                        // 忽略无法解析的值
                        continue;
                    }
                }
            }
            route.setTravelTimes(travelTimes);

            // 解析容量（第31列，索引30）
            double capacity = 200; // 默认值
            if (rowData.length > 30 && !rowData[30].trim().isEmpty()) {
                try {
                    capacity = Double.parseDouble(rowData[30]);
                } catch (NumberFormatException e) {
                    // 使用默认值
                }
            }
            route.setCapacity((int) capacity);
            route.setRemainingCapacity((int) capacity);

            // 计算总旅行时间、总成本
            double totalTravelTime = travelTimes.stream().mapToDouble(Double::doubleValue).sum();
            double totalCost = costs.stream().mapToDouble(Double::doubleValue).sum();

            route.setTotalTravelTime(totalTravelTime);
            route.setTotalCost(totalCost);

            return route;
        } catch (Exception e) {
            System.err.println("解析CSV行失败: " + e.getMessage() + ", 数据: " +
                    (rowData.length > 5 ? String.join(",", java.util.Arrays.copyOf(rowData, 5)) : String.join(",", rowData)) + "...");
            return null;
        }
    }

    /**
     * 从CSV行数据创建货物实例
     *
     * @param rowData   CSV行数据
     * @param headerMap 列标题映射
     * @param dataId    数据ID
     * @return 货物实例
     */
    private Shipment parseShipmentFromCsvRow(String[] rowData, Map<String, Integer> headerMap, Integer dataId) {
        try {
            Shipment shipment = new Shipment();
            shipment.setDataId(dataId);

            // 解析货物ID
            Integer shipmentId = getValueFromHeader(rowData, headerMap, "shipment index");
            shipment.setShipmentId(shipmentId != null ? shipmentId : 0);

            // 解析起始节点
            Integer originNode = getValueFromHeader(rowData, headerMap, "Origin");
            shipment.setOriginNode(City.fromCode(originNode != null ? originNode : 0));

            // 解析目标节点
            Integer destinationNode = getValueFromHeader(rowData, headerMap, "destination");
            shipment.setDestinationNode(City.fromCode(destinationNode != null ? destinationNode : 0));

            // 解析需求量
            Integer demand = getValueFromHeader(rowData, headerMap, "Demand");
            shipment.setDemand(demand != null ? demand : 0);

            // 解析时间价值
            Integer timeValue = getValueFromHeader(rowData, headerMap, "Time value(CNY/TEU)");
            shipment.setTimeValue(timeValue != null ? timeValue : 0);

            return shipment;
        } catch (Exception e) {
            System.err.println("解析货物CSV行失败: " + e.getMessage() + ", 数据: " +
                    (rowData.length > 5 ? String.join(",", java.util.Arrays.copyOf(rowData, 5)) : String.join(",", rowData)) + "...");
            return null;
        }
    }

    /**
     * 从CSV行数据创建匹配结果实例
     *
     * @param shipmentHeaderRow 货物标题行
     * @param routeRow          路线数据行
     * @param statisticsLines   统计信息行数据
     * @param dataId            数据ID
     * @return 匹配结果实例
     */
    private MatchResult parseMatchResultFromCsvRows(String[] shipmentHeaderRow, String[] routeRow,
                                                    List<String> statisticsLines, Integer dataId) {
        try {
            MatchResult matchResult = new MatchResult();
            matchResult.setDataId(dataId);

            // 解析统计信息
            for (String row : statisticsLines) {
                String[] parts = row.split(",", -1);
                if (parts.length >= 2) {
                    String key = parts[0].trim();
                    String value = parts[1].trim();

                    try {
                        switch (key) {
                            case "Total capacity in route":
                                matchResult.setTotalCapacity(Integer.parseInt(value));
                                break;
                            case "Total container number in shipment":
                                matchResult.setTotalContainerNumber(Integer.parseInt(value));
                                break;
                            case "Total matched container number":
                                matchResult.setTotalMatchedContainerNumber(Integer.parseInt(value));
                                break;
                            case "Stable or not":
                                matchResult.setIsStable("true".equalsIgnoreCase(value));
                                break;
                            case "Iteration num":
                                matchResult.setIterationNum(Integer.parseInt(value));
                                break;
                            case "Restart num":
                                matchResult.setRestartNum(Integer.parseInt(value));
                                break;
                            case "CPU time":
                                matchResult.setCpuTime(Double.parseDouble(value));
                                break;
                        }
                    } catch (NumberFormatException e) {
                        System.err.println("解析统计信息时出错，键: " + key + ", 值: " + value);
                        throw e;
                    }
                }
            }

            return matchResult;
        } catch (Exception e) {
            System.err.println("解析匹配结果CSV行失败: " + e.getMessage());
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 解析匹配详情数据
     *
     * @param shipmentHeaderRow 货物标题行
     * @param routeRow          路线数据行
     * @param dataId            数据ID
     * @return 匹配详情列表
     */
    private List<MatchDetail> parseMatchDetailsFromCsvRows(String[] shipmentHeaderRow, String[] routeRow, Integer dataId) {
        List<MatchDetail> matchDetails = new ArrayList<>();

        try {
            // 解析货物索引（基于标题行的数字）
            List<Integer> shipmentIndices = new ArrayList<>();
            for (int i = 1; i < shipmentHeaderRow.length; i++) {
                String header = shipmentHeaderRow[i].trim();
                if (!header.isEmpty() && !"Shipment".equals(header)) {
                    try {
                        shipmentIndices.add(Integer.parseInt(header));
                    } catch (NumberFormatException e) {
                        System.err.println("解析货物索引时出错，值: " + header);
                    }
                }
            }

            // 解析路线分配（跳过第一列"Route"）
            List<Integer> routeAssignments = new ArrayList<>();
            for (int i = 1; i < routeRow.length && i < shipmentHeaderRow.length; i++) {
                String value = routeRow[i].trim();
                String header = shipmentHeaderRow[i].trim();
                if (!value.isEmpty() && !header.isEmpty() && !"Shipment".equals(header)) {
                    if ("Self".equalsIgnoreCase(value)) {
                        // 对于"Self"，我们使用特殊值-1表示
                        routeAssignments.add(-1);
                    } else {
                        try {
                            routeAssignments.add(Integer.parseInt(value));
                        } catch (NumberFormatException e) {
                            System.err.println("解析路线分配时出错，值: " + value);
                        }
                    }
                }
            }

            // 创建匹配详情
            for (int i = 0; i < shipmentIndices.size() && i < routeAssignments.size(); i++) {
                MatchDetail detail = new MatchDetail();
                detail.setDataId(dataId);
                detail.setShipmentId(shipmentIndices.get(i));
                detail.setRouteId(routeAssignments.get(i));
                // 简化匹配状态设置逻辑
                detail.setMatchStatus(routeAssignments.get(i) != -1 ? 1 : 0);
                matchDetails.add(detail);
            }
        } catch (Exception e) {
            System.err.println("解析匹配详情CSV行失败: " + e.getMessage());
            e.printStackTrace();
        }

        return matchDetails;
    }

    /**
     * 从头部映射中获取值
     *
     * @param rowData   行数据
     * @param headerMap 头部映射
     * @param header    头部名称
     * @return 解析的整数值，如果找不到则返回null
     */
    private Integer getValueFromHeader(String[] rowData, Map<String, Integer> headerMap, String header) {
        Integer index = headerMap.get(header);
        if (index != null && index < rowData.length) {
            String value = rowData[index].trim();
            if (!value.isEmpty()) {
                try {
                    return Integer.parseInt(value);
                } catch (NumberFormatException e) {
                    // 返回null表示解析失败
                    return null;
                }
            }
        }
        return null;
    }

    /**
     * 自定义MultipartFile实现类
     */
    private static class CustomMultipartFile implements MultipartFile {
        private final File file;

        public CustomMultipartFile(File file) {
            this.file = file;
        }

        @Override
        public String getName() {
            return file.getName();
        }

        @Override
        public String getOriginalFilename() {
            return file.getName();
        }

        @Override
        public String getContentType() {
            return "text/csv";
        }

        @Override
        public boolean isEmpty() {
            return file.length() == 0;
        }

        @Override
        public long getSize() {
            return file.length();
        }

        @Override
        public byte[] getBytes() throws IOException {
            return Files.readAllBytes(file.toPath());
        }

        @Override
        public InputStream getInputStream() throws IOException {
            return Files.newInputStream(file.toPath());
        }

        @Override
        public void transferTo(File dest) throws IOException, IllegalStateException {
            Files.copy(file.toPath(), dest.toPath());
        }
    }
}